package org.dark.fund.service;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dark.fund.api.IFundService;
import org.dark.fund.api.IMyFundService;
import org.dark.fund.api.IRateReturnService;
import org.dark.fund.api.dto.MyFundToday;
import org.dark.fund.dao.entity.Fund;
import org.dark.fund.dao.entity.MyFund;
import org.dark.fund.dao.entity.RateReturn;
import org.dark.fund.dao.mapper.MyFundMapper;
import org.dark.fund.enums.ResultCode;
import org.dark.fund.exceptions.FundBizException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wanlh
 * @since 2021-04-29
 */
@Service
public class MyFundServiceImpl extends ServiceImpl<MyFundMapper, MyFund> implements IMyFundService {

    @Autowired
    IFundService fundService;

    @Autowired
    IRateReturnService rateReturnService;

    @Override
    public List<String> getMyFundIds(String userId) {
        return lambdaQuery().select(MyFund::getFundCode).eq(MyFund::getUserId, userId).list()
                .stream().map(MyFund::getFundCode).collect(Collectors.toList());
    }

    @Override
    public List<Fund> getMyFunds(String userId) {
        List<String> fundIds = getMyFundIds(userId);
        return fundService.getBatchFund(fundIds);
    }

    @Override
    public List<MyFundToday> getMyFundToday(String userId) {
        List<String> fundIds = getMyFundIds(userId);
        if (CollectionUtil.isEmpty(fundIds)) {
            return Collections.emptyList();
        }
        Map<String, Fund> fundBaseInfo = fundService.getBatchFund(fundIds).stream()
                .collect(Collectors.toMap(Fund::getFundCode, Function.identity()));
        Map<String, RateReturn> rateInfo = rateReturnService.getTodayRate(fundIds);
        List<MyFundToday> result = new ArrayList<>(fundIds.size());
        fundIds.forEach(fundCode -> {
            RateReturn rate = rateInfo.get(fundCode);
            if (rate == null) {
                return;
            }
            Fund fund = fundBaseInfo.get(fundCode);
            result.add(MyFundToday.builder().fundCode(fundCode).fundName(fund.getFundName())
                    .rate(rate.getLastOneDayRate()).value(new BigDecimal(rate.getNetAssetValue()))
                    .build());
        });
        return result;
    }

    @Override
    public Boolean addMyFund(String userId, String fundCode) {
        if (0 < lambdaQuery().eq(MyFund::getFundCode, fundCode).eq(MyFund::getUserId, userId).count()) {
            throw new FundBizException(ResultCode.EXISTS_FUND_ATTACH);
        }
        return save(new MyFund(userId, fundCode));
    }

    @Override
    public Boolean removeMyFund(String userId, String fundCode) {
        return lambdaUpdate().eq(MyFund::getFundCode, fundCode).eq(MyFund::getUserId, userId).remove();
    }
}
